/**
 * TextFormatTests
 *
 * @author Chris Pratt
 *
 * 9/1/2006
 */
package com.anodyzed.onyx.text;

import com.anodyzed.onyx.log.LogBuilder;
import com.anodyzed.onyx.log.sysout.SysOutLogFactory;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;

public class TextFormatTests {
  public static class TestData {
    public class Inner {
      public String getText () {
        return "inner";
      } //getText
    } //*Inner

    public String getText () {
      return "outer";
    } //getText

    public Object getInner () {
      return new Inner();
    } //getInner

    public Date getDate () {
      return new GregorianCalendar(1965,Calendar.JUNE,18).getTime();
    } //getDate

    public int getNum () {
      return 42;
    } //getNum

    public String getStr () {
      return "Test";
    } //getStr

  } //*TestData

  public TestData data = new TestData();

  /**
   * Setup the Test Harness
   */
  @BeforeClass public static void setup () {
    LogBuilder.setLogFactory(new SysOutLogFactory());
  } //setup

  /**
   * Perform a jUnit Test on the TextFormat Bean introspection capability
   */
  @Test public void testBean () {
    assertEquals("Test the Bean.traversal = outer - inner",TextFormat.format("Test the Bean.traversal = {0.text} - {0.inner.text}",data));
    assertEquals("Test the Bean.traversal = outer - inner",TextFormat.format("Test the Bean.traversal = {text} - {inner.text}",data));
  } //testBean

  /**
   * Perform a jUnit Test on the TextFormat List Formatting capability
   */
  @Test public void testList () {
    List<String> list = new ArrayList<String>();
    list.add("one");
    list.add("two");
    list.add("three");
    assertEquals("Test the Bean.size = 3",TextFormat.format("Test the Bean.size = {0.size}",list));
    assertEquals("Test List CSV = [one,two,three]",TextFormat.format("Test List CSV = [{0,list,csv}]",list));
    assertEquals("Test List Fixed = \"on00twothree  \"",TextFormat.format("Test List Fixed = \"{0,list,2,-5,7}\"",list));
  } //testList

  /**
   * Perform a jUnit Test on the TextFormat Number formatting capablility
   */
  @Test public void testNumber () {
    assertEquals("Test the Int = 602,214,179,000,000,000,000,000",TextFormat.format("Test the Int = {0,number}",6.02214179E23));
    assertEquals("Test the Integer = 843,215,975",TextFormat.format("Test the Integer = {0,number,integer}",843215975));
    assertEquals("Test the Currency = $785,141,658.00",TextFormat.format("Test the Currency = {0,number,currency}",785141658));
    assertEquals("Test the Percent = 2,300%",TextFormat.format("Test the Percent = {0,number,percent}",23));
    assertEquals("Test the Pattern = (1,024.42)",TextFormat.format("Test the Pattern = {0,number,#,##0.00;(#,##0.00)}",-1024.42));
  } //testNumber

  /**
   * Perform a jUnit Test on the TextFormat Fraction formatting capability
   */
  @Test public void testFraction () {
    assertEquals("Test the Pattern = 1/2",TextFormat.format("Test the Pattern = {0,number,fraction}",0.5));
    assertEquals("Test the Pattern = 1/3",TextFormat.format("Test the Pattern = {0,number,fraction}",1.0 / 3.0));
    assertEquals("Test the Pattern = 2/3",TextFormat.format("Test the Pattern = {0,number,fraction}","4/6"));
    assertEquals("Test the Pattern = 1 1/2",TextFormat.format("Test the Pattern = {0,number,fraction}","1.5"));
  } //testFraction

  /**
   * Perform a jUnit Test on the TextFormat Date formatting capability
   */
  @Test public void testDate () {
    Date d = new GregorianCalendar(1965,Calendar.JUNE,18).getTime();
    assertEquals("Test the Date = 6/18/1965",TextFormat.format("Test the Date = {0,date,M/d/yyyy}",d));
    assertEquals("Test the Date = Friday, June 18, 1965",TextFormat.format("Test the Date = {0,date,full}",d));
    assertEquals("Test the Date = June 18, 1965",TextFormat.format("Test the Date = {0,date,long}",d));
    assertEquals("Test the Date = Jun 18, 1965",TextFormat.format("Test the Date = {0,date,medium}",d));
    assertEquals("Test the Date = 6/18/65",TextFormat.format("Test the Date = {0,date,short}",d));
    assertEquals("Test the Date = 6/18/65 12:00 AM",TextFormat.format("Test the Date = {0,date}",d));
  } //testDate

  /**
   * Perform a jUnit Test on the TextFormat Time formatting capability
   */
  @Test public void testTime () {
    Date d = new GregorianCalendar(1980,Calendar.NOVEMBER,7,20,31,23).getTime();
    assertEquals("Test the Time = 8:31 PM",TextFormat.format("Test the Time = {0,time,h:mm a}",d));
    assertEquals("Test the Time = 8:31:23 PM PST",TextFormat.format("Test the Time = {0,time,full}",d));
    assertEquals("Test the Time = 8:31:23 PM PST",TextFormat.format("Test the Time = {0,time,long}",d));
    assertEquals("Test the Time = 8:31:23 PM",TextFormat.format("Test the Time = {0,time,medium}",d));
    assertEquals("Test the Time = 8:31 PM",TextFormat.format("Test the Time = {0,time,short}",d));
    assertEquals("Test the Time = 8:31:23 PM",TextFormat.format("Test the Time = {0,time}",d));
  } //testTime

  /**
   * Perform a jUnit Test on the TextFormat Boolean formatting capability
   */
  @Test public void testBoolean () {
    assertEquals("I think the answer is yup",TextFormat.format("I think the answer is {0,boolean,yup|nope}",true));
    assertEquals("I'm pretty sure it's nope",TextFormat.format("I''m pretty sure it''s {0,boolean,yup|nope}","false"));
  } //testBoolean

  /**
   * Perform a jUnit Test on the TextFormat Map Data Access capability
   */
  @Test public void testMap () {
    Map<String,Object> map = new HashMap<String,Object>();
    map.put("bean",data);
    assertEquals("Test the Mapped String = Test",TextFormat.format("Test the Mapped String = {bean.str}",map));
    assertEquals("Test the Mapped Number = 42",TextFormat.format("Test the Mapped Number = {bean.num,number}",map));
    assertEquals("Test the Mapped Date = 6/18/1965",TextFormat.format("Test the Mapped Date = {bean.date,date,M/d/yyyy}",map));
  } //testMap

  /**
   * Perform a jUnit Test on the TextFormat Choice Format capability 
   */
  @Test(expected=IllegalArgumentException.class) public void testChoice () {
    TextFormat choice = new TextFormat("The disk \"{1}\" contains {0,choice,0#no files|1#one file|1<{0,number,integer} files}.");
    assertEquals("The disk \"none.test\" contains no files.",choice.format(0,"none.test"));
    assertEquals("The disk \"one.test\" contains one file.",choice.format(1,"one.test"));
    assertEquals("The disk \"big.test\" contains 1,273 files.",choice.format(1273,"big.test"));
    TextFormat.format("This test should throw an IllegalArgumentException, {0,choice}",1);
  } //testChoice

  /**
   * Perform a jUnit Test on the TextFormat Substring Format capability
   */
  @Test public void testSubstring () {
    assertEquals("Test first five characters of \"abcdefghij\" = \"abcde\"",TextFormat.format("Test first five characters of \"abcdefghij\" = \"{0,substring,0-5}\"","abcdefghij"));
    assertEquals("Test last five characters of \"abcdefghij\" = \"fghij\"",TextFormat.format("Test last five characters of \"abcdefghij\" = \"{0,substring,5}\"","abcdefghij"));
    assertEquals("Test middle five characters of \"abcdefghij\" = \"defgh\"",TextFormat.format("Test middle five characters of \"abcdefghij\" = \"{0,substring,3-8}\"","abcdefghij"));
    assertEquals("Test first three characters of \"a\" = \"a\"",TextFormat.format("Test first three characters of \"a\" = \"{0,substring,0..3}\"","a"));
    assertEquals("Test character 15 thru 17 of \"abcdefghij\" = \"\"",TextFormat.format("Test character 15 thru 17 of \"abcdefghij\" = \"{0,substring,15-17}\"","abcdefghij"));
    assertEquals("Test first two characters of 12345 = 12",TextFormat.format("Test first two characters of 12345 = {0,substring,0,2}",12345));
    assertEquals("Test first two characters of outer.inner.text = \"in\"",TextFormat.format("Test first two characters of outer.inner.text = \"{0.inner.text,substring,0..2}\"",data));
  } //testSubstring

  /**
   * Perform a jUnit Test on the TextFormat ability to Override Text Formatters
   */
  @Test public void testFormatOverride () {
    assertEquals("Test that a null integer parameter defaults to null",TextFormat.format("Test that a null integer parameter defaults to {0,number,integer}",(Object)null));
    TextFormat fmt = new TextFormat("Test that an overridden integer parameter returns {0,number,integer}");
    fmt.addFormatter("number",ZeroNullNumberFormatter.class);
    assertEquals("Test that an overridden integer parameter returns 0",fmt.format((Object)null));
  } //testFormatOverride

  /**
   * Perform a jUnit Test on the TextFormat subformat capability
   */
//  @Test public void testSubformat () {
//  } //testSubformat

  /**
   * jUnit 3.x Test Suite
   *
   * @return Adapted Test Suite
   */
  public static junit.framework.Test suite () {
    return new junit.framework.JUnit4TestAdapter(TextFormatTests.class);
  } //suite

} //*TextFormatTests
